package com.zxmc.server.service.impl;

import java.io.*;
import java.util.*;

import com.alibaba.fastjson2.JSON;
import com.zxmc.common.context.BaseContext;
import com.zxmc.common.result.PageResult;
import com.zxmc.pojo.dto.NovelQueryDto;
import com.zxmc.pojo.dto.PageNovelQueryDto;
import com.zxmc.pojo.entity.Novel;
import com.zxmc.pojo.entity.ReadingHistory;
import com.zxmc.pojo.vo.NovelVO;
import com.zxmc.server.service.NovelService;
import com.zxmc.server.service.NovelTypeService;
import com.zxmc.server.service.RecommendationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@EnableScheduling
public class RecommendationServiceImpl implements RecommendationService {
    @Autowired
    private NovelService novelService;
    @Autowired
    private NovelTypeService novelTypeService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RecommendationService self; // 注入自身代理对象
    public PageResult recommendNovels(PageNovelQueryDto pageNovelQueryDto) {
        int userId = BaseContext.getCurrentId();
        List<Integer> recommendedNovels = self.callRecommandFun(userId);
        log.info("recommendedNovels,{}",recommendedNovels);
        // 分页处理
        int page = pageNovelQueryDto.getPage();
        int pageSize = pageNovelQueryDto.getPageSize();
        int total = recommendedNovels.size();
        int start = (page - 1) * pageSize;
        int end = Math.min(start + pageSize, total);
        List<Integer> pagedRecommendedNovels = recommendedNovels.subList(start, end);
//        System.out.println(pagedRecommendedNovels);
        // 根据novelId查询数据库中的小说
        List<Novel> novels = new ArrayList<>();
        for (Integer novelId : pagedRecommendedNovels) {
            NovelQueryDto novelQueryDto = new NovelQueryDto();
            novelQueryDto.setId(novelId);
            Novel novel = novelService.list(novelQueryDto).get(0);
            if (novel != null) {
                novels.add(novel);
            }
        }
        List<NovelVO> novelVOS1 = novelService.getNovelVOs(pageNovelQueryDto, novels, novelTypeService);
        // 返回分页结果
        PageResult pageResult = new PageResult(total,novelVOS1);
        return pageResult;
    }

    @Cacheable("recommendCache")
    public List<Integer> callRecommandFun(int userId){
        List<Integer> recommendedNovels = new ArrayList<>();

        try {
            // 获取 Redis 中 novelHistory:userId: 下的所有内容
            String keyPattern = "novelHistory:" + userId + ":*";
//            System.out.println(keyPattern);
            Set<String> keys = redisTemplate.keys(keyPattern);
//            System.out.println(keys);
            List<ReadingHistory> novelHistoryValues = new ArrayList<>();
            if (!keys.isEmpty()) {
                for (String key : keys) {
                    Object value = redisTemplate.opsForValue().get(key);
                    if (value != null) {
                        // 使用 FastJSON 将 JSONObject 转换为 ReadingHistory 对象
                        ReadingHistory readingHistory = JSON.to(ReadingHistory.class, value);
                        novelHistoryValues.add(readingHistory);

                    }
                }
            }
            log.info("novelHistoryValues,{}",novelHistoryValues);
            // 从数据库获取数据并转换为 Map 列表
            List<Map<String, Object>> dfNovel = convertToMapList(novelService.listRecommend());
            List<Map<String, Object>> dfNovelType = convertToMapList(novelTypeService.listAll());
            List<Map<String, Object>> dfReadingHistory = convertToMapList(novelHistoryValues);

            // 将数据写入临时文件
            File dfNovelFile = File.createTempFile("dfNovel", ".json");
            File dfNovelTypeFile = File.createTempFile("dfNovelType", ".json");
            File dfReadingHistoryFile = File.createTempFile("dfReadingHistory", ".json");

            writeJsonToFileUsingFastJson(dfNovel, dfNovelFile);
            writeJsonToFileUsingFastJson(dfNovelType, dfNovelTypeFile);
            writeJsonToFileUsingFastJson(dfReadingHistory, dfReadingHistoryFile);

            //部署云
//            ProcessBuilder pb = new ProcessBuilder("python", "/usr/server/springboot/recommend_novels.py",
//                    String.valueOf(userId), dfNovelFile.getAbsolutePath(), dfNovelTypeFile.getAbsolutePath(),
//                    dfReadingHistoryFile.getAbsolutePath());
            ProcessBuilder pb = new ProcessBuilder("python", "bishe_back\\src\\main\\resources\\static\\recommend_novels.py",
                    String.valueOf(userId), dfNovelFile.getAbsolutePath(), dfNovelTypeFile.getAbsolutePath(),
                    dfReadingHistoryFile.getAbsolutePath());
            Process process = pb.start();

            int exitCode = process.waitFor();
            if (exitCode != 0) {
                System.err.println("Python script execution failed with exit code: " + exitCode);
            }
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.replace("[", "").replace("]", "").replace(" ", "");
                String[] ids = line.split(",");
                System.out.println(Arrays.toString(ids));
                for (String id : ids) {
                    if (!id.isEmpty()) {
                        recommendedNovels.add(Integer.parseInt(id));
                    }
                }
            }
            // 读取错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String errorLine;
            while ((errorLine = errorReader.readLine()) != null) {
                System.err.println("Python script error: " + errorLine);
            }

            // 删除临时文件
            dfNovelFile.delete();
            dfNovelTypeFile.delete();
            dfReadingHistoryFile.delete();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        return recommendedNovels;
    }


    private <T> List<Map<String, Object>> convertToMapList(List<T> entities) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (T entity : entities) {
            Map<String, Object> map = new HashMap<>();
            // 假设实体类有对应的 Getter 方法
            java.lang.reflect.Method[] methods = entity.getClass().getMethods();
            for (java.lang.reflect.Method method : methods) {
                if (method.getName().startsWith("get") && !method.getName().equals("getClass")) {
                    try {
                        String fieldName = method.getName().substring(3);
                        fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
                        Object value = method.invoke(entity);
                        map.put(fieldName, value);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            mapList.add(map);
        }
        return mapList;
    }
    private void writeJsonToFileUsingFastJson(List<Map<String, Object>> data, File file) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
            writer.write(JSON.toJSONString(data));
        }
    }
}
